usingnamespacestd; //before entering main function, all global (static) variables will be initialized, in which process plugins are registered to factory. intmain(){ Factory & factory = Factory::Instance(); //p1, p2 are unique_ptr<Base>, so caller own new created plugin object. auto p1 = factory.Create("Plugin1"); auto p2 = factory.Create("Plugin2"); auto p3 = factory.Create("Plugin3"); if (p1) { p1->do_something(); } if (p2) { p2->do_something(); } if (p3) { p3->do_something(); } }
typedefstd::function<Base*()> CreatorFunc; // ATTENTION: can not use register as function name, becase register is a keyword in C++11 template<typename Derived> boolRegister(conststd::string & plugin_name){ CreatorFunc creator_func = Creator<Derived>; auto ret = _map.insert(std::make_pair(plugin_name, creator_func)); return ret.second; }
// do not return raw pointer directly, use smart pointer std::unique_ptr<Base> Create(conststd::string & plugin_name) { auto iter = _map.find(plugin_name); if (iter == _map.end()) returnstd::unique_ptr<Base>(nullptr); returnstd::unique_ptr<Base>((iter->second)()); } private: template<typename Derived> static Derived* Creator(){ returnnew Derived(); }
// forbid copy constructor and assign operation, // to make sure Factory is a Singleton Factory(const Factory &) = delete; Factory & operator = (const Factory &) = delete; // forbid move constructor and move assign operation, // to make sure Factory is a Singleton Factory(Factory &&) = delete; Factory & operator = (Factory &&) = delete; };
// macro is used widely in many factory pattern implementation. But, macro is ugly, it make program hard to comprehend and debug, so avoid using it #define REGISTER_PLUGIN(CLASSNAME) \ staticconstauto CLASSNAME##register_result = Factory::Instance().Register<CLASSNAME>(#CLASSNAME); \